﻿// Decompiled with JetBrains decompiler
// Type: Netick.Unity.NetworkAnimator
// Assembly: Netick.Unity, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E128C7FD-39ED-4452-86AC-6EC748457030
// Assembly location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.Unity.dll
// XML documentation location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.Unity.xml

using System;
using System.Collections.Generic;
using UnityEngine;

#nullable disable
namespace Netick.Unity;

/// <summary>
/// This component is used to replicate Unity's Animator parameters and states.
/// </summary>
[AddComponentMenu("Netick/Network Animator")]
[RequireComponent(typeof (Animator))]
[DisallowMultipleComponent]
[IgnoreCodeGen]
public class NetworkAnimator : NetworkBehaviour
{
  [SerializeField]
  [HideInInspector]
  private NetworkAnimator.NetworkAnimatorRepConditions Settings = NetworkAnimator.NetworkAnimatorRepConditions.SyncParameters;
  [SerializeField]
  private InterpolationSource _interpolationSource;
  private AdaptiveRemoteInterpolation _adaptiveRemoteInterpolation;
  [SerializeField]
  internal int[] IndexToHash;
  private Dictionary<int, int> HashToIndex;
  private int[] ProToLastValue;
  private HashSet<int> Triggers = new HashSet<int>(16 /*0x10*/);
  private Dictionary<int, int> HashToTriggerOffset = new Dictionary<int, int>(16 /*0x10*/);
  private AnimatorControllerParameter[] Parameters;
  private int OffsetToLayers;
  private int StateSizeWords;
  private const float _floatPrecision = 0.001f;
  private const float _floatInversePrecision = 999.999939f;

  public Animator Animator { get; private set; }

  public InterpolationSource InterpolationSource
  {
    get => this._interpolationSource;
    set => this._interpolationSource = value;
  }

  private void Awake()
  {
    this.Animator = this.GetComponent<Animator>();
    this.Parameters = this.Animator.parameters;
    this.HashToIndex = new Dictionary<int, int>();
    this.ProToLastValue = new int[this.Parameters.Length];
    int num = (this.Settings & NetworkAnimator.NetworkAnimatorRepConditions.SyncParameters) == NetworkAnimator.NetworkAnimatorRepConditions.SyncParameters ? 1 : 0;
    bool flag1 = (this.Settings & NetworkAnimator.NetworkAnimatorRepConditions.SyncLayerWeights) == NetworkAnimator.NetworkAnimatorRepConditions.SyncLayerWeights;
    bool flag2 = (this.Settings & NetworkAnimator.NetworkAnimatorRepConditions.SyncState) == NetworkAnimator.NetworkAnimatorRepConditions.SyncState;
    this.StateSizeWords = 1;
    this.OffsetToLayers = 0;
    if (num != 0)
    {
      for (int index = 0; index < this.Parameters.Length; ++index)
        ++this.StateSizeWords;
      this.OffsetToLayers = this.StateSizeWords;
    }
    for (int index = 0; index < this.Animator.layerCount; ++index)
    {
      if (flag1)
        ++this.StateSizeWords;
      if (flag2)
        this.StateSizeWords += 2;
    }
    this.HashToTriggerOffset.Clear();
    for (int index = 0; index < this.Parameters.Length; ++index)
    {
      if (this.Parameters[index].type == AnimatorControllerParameterType.Trigger)
        this.HashToTriggerOffset.Add(this.Parameters[index].nameHash, index);
    }
    if (!this.HashToIndex.ContainsKey(0))
      this.HashToIndex.Add(0, 0);
    for (int index = 0; index < this.IndexToHash.Length; ++index)
      this.HashToIndex.Add(this.IndexToHash[index], index);
  }

  public override void NetworkAwake()
  {
    this._adaptiveRemoteInterpolation = this.Entity.AdaptiveRemoteInterpolation;
  }

  public override void NetworkReset()
  {
    for (int index = 0; index < this.ProToLastValue.Length; ++index)
      this.ProToLastValue[index] = 0;
  }

  public override int InternalGetStateSizeWords() => this.StateSizeWords;

  public override unsafe void NetworkRender()
  {
    Interpolation interpolation = (this.IsServer ? 1 : 0) == 0 ? (this._interpolationSource != InterpolationSource.PredictedSnapshot ? (this._interpolationSource != InterpolationSource.RemoteSnapshot ? (!this.Entity.IsPredicted ? (this._adaptiveRemoteInterpolation != null ? (Interpolation) this._adaptiveRemoteInterpolation : (Interpolation) this.Object.Engine.RemoteInterpolation) : (Interpolation) this.Object.Engine.LocalInterpolation) : (this._adaptiveRemoteInterpolation != null ? (Interpolation) this._adaptiveRemoteInterpolation : (Interpolation) this.Object.Engine.RemoteInterpolation)) : (Interpolation) this.Object.Engine.LocalInterpolation) : (Interpolation) this.Object.Engine.LocalInterpolation;
    if (!interpolation.HasSnapshots)
      return;
    long num1 = this.Entity.StateOffsetBytes + ((sbyte*) this.StatePtr - (sbyte*) this.Entity.StatePtr);
    float alpha = interpolation.Alpha;
    byte* ptr1 = (byte*) interpolation.FromSnapshot.Blocks[this.Entity.BlockIndex].Ptr;
    byte* ptr2 = (byte*) interpolation.ToSnapshot.Blocks[this.Entity.BlockIndex].Ptr;
    int* from = (int*) (ptr1 + num1);
    int* to = (int*) (ptr2 + num1);
    int num2 = (this.Settings & NetworkAnimator.NetworkAnimatorRepConditions.SyncParameters) == NetworkAnimator.NetworkAnimatorRepConditions.SyncParameters ? 1 : 0;
    bool syncLW = (this.Settings & NetworkAnimator.NetworkAnimatorRepConditions.SyncLayerWeights) == NetworkAnimator.NetworkAnimatorRepConditions.SyncLayerWeights;
    bool syncS = (this.Settings & NetworkAnimator.NetworkAnimatorRepConditions.SyncState) == NetworkAnimator.NetworkAnimatorRepConditions.SyncState;
    if (num2 != 0)
      this.Properties_NetcodeToAnimator_Lerp(from, to, alpha);
    this.Layers_NetcodeToAnimator(from, to, alpha, true, syncLW, syncS);
  }

  public override unsafe void GameEngineIntoNetcode()
  {
    int num = (this.Settings & NetworkAnimator.NetworkAnimatorRepConditions.SyncParameters) == NetworkAnimator.NetworkAnimatorRepConditions.SyncParameters ? 1 : 0;
    bool syncLW = (this.Settings & NetworkAnimator.NetworkAnimatorRepConditions.SyncLayerWeights) == NetworkAnimator.NetworkAnimatorRepConditions.SyncLayerWeights;
    bool syncS = (this.Settings & NetworkAnimator.NetworkAnimatorRepConditions.SyncState) == NetworkAnimator.NetworkAnimatorRepConditions.SyncState;
    if (num != 0)
      this.Properties_AnimatorToNetcode();
    this.Layers_AnimatorToNetcode(this.StatePtr, syncLW, syncS);
  }

  public override unsafe void NetcodeIntoGameEngine()
  {
    int num = (this.Settings & NetworkAnimator.NetworkAnimatorRepConditions.SyncParameters) == NetworkAnimator.NetworkAnimatorRepConditions.SyncParameters ? 1 : 0;
    bool syncLW = (this.Settings & NetworkAnimator.NetworkAnimatorRepConditions.SyncLayerWeights) == NetworkAnimator.NetworkAnimatorRepConditions.SyncLayerWeights;
    bool syncS = (this.Settings & NetworkAnimator.NetworkAnimatorRepConditions.SyncState) == NetworkAnimator.NetworkAnimatorRepConditions.SyncState;
    if (num != 0)
      this.Properties_NetcodeToAnimator();
    this.Layers_NetcodeToAnimator(this.StatePtr, (int*) null, 0.0f, false, syncLW, syncS);
  }

  private unsafe void Layers_AnimatorToNetcode(int* data, bool syncLW, bool syncS)
  {
    int num1 = 0;
    if (syncLW)
      ++num1;
    if (syncS)
      num1 += 2;
    if (!syncLW && !syncS)
      return;
    for (int layerIndex = 0; layerIndex < this.Animator.layerCount; ++layerIndex)
    {
      int num2 = layerIndex * num1 + this.OffsetToLayers;
      AnimatorStateInfo animatorStateInfo = this.Animator.GetCurrentAnimatorStateInfo(layerIndex);
      int fullPathHash = animatorStateInfo.fullPathHash;
      animatorStateInfo = this.Animator.GetCurrentAnimatorStateInfo(layerIndex);
      float normalizedTime = animatorStateInfo.normalizedTime;
      int num3 = this.HashToIndex[fullPathHash];
      int* data1 = &0;
      int* numPtr = &0;
      if (syncLW)
      {
        NetickUnityUtils.SetFloat(data1, this.Animator.GetLayerWeight(layerIndex), 999.999939f);
        Entity.InternalDirtify((INetickNetworkScript) this, data1, this.StatePtr + num2++, 1, 0);
      }
      if (syncS)
      {
        *numPtr = num3;
        int* data2 = numPtr;
        int* statePtr1 = this.StatePtr;
        int num4 = num2;
        int num5 = num4 + 1;
        IntPtr num6 = (IntPtr) num4 * 4;
        IntPtr p1 = (IntPtr) statePtr1 + num6;
        Entity.InternalDirtify((INetickNetworkScript) this, data2, (int*) p1, 1, 0);
        NetickUnityUtils.SetFloat(data1, normalizedTime, 999.999939f);
        int* data3 = data1;
        int* statePtr2 = this.StatePtr;
        int num7 = num5;
        int num8 = num7 + 1;
        IntPtr num9 = (IntPtr) num7 * 4;
        IntPtr p2 = (IntPtr) statePtr2 + num9;
        Entity.InternalDirtify((INetickNetworkScript) this, data3, (int*) p2, 1, 0);
      }
    }
  }

  private unsafe void Layers_NetcodeToAnimator(
    int* from,
    int* to,
    float alpha,
    bool lerp,
    bool syncLW,
    bool syncS)
  {
    int num1 = 0;
    if (syncLW)
      ++num1;
    if (syncS)
      num1 += 2;
    if (!syncLW && !syncS)
      return;
    for (int index1 = 0; index1 < this.Animator.layerCount; ++index1)
    {
      int num2 = index1 * num1 + this.OffsetToLayers;
      if (syncLW)
      {
        float weight = lerp ? this.InterpolateFloat(from + num2, to + num2, alpha) : NetickUnityUtils.GetFloat(from + num2, 1f / 1000f);
        ++num2;
        this.Animator.SetLayerWeight(index1, weight);
      }
      if (syncS)
      {
        int* numPtr = from;
        int num3 = num2;
        int num4 = num3 + 1;
        IntPtr num5 = (IntPtr) num3 * 4;
        int index2 = *(int*) ((IntPtr) numPtr + num5);
        float normalizedTime = lerp ? this.InterpolateFloat(from + num4, to + num4, alpha) : NetickUnityUtils.GetFloat(from + num4, 1f / 1000f);
        int num6 = num4 + 1;
        int stateNameHash = this.IndexToHash[index2];
        if (stateNameHash != 0 && this.Animator.enabled)
          this.Animator.Play(stateNameHash, index1, normalizedTime);
      }
    }
  }

  private unsafe void Properties_AnimatorToNetcode()
  {
    for (int index = 0; index < this.Parameters.Length; ++index)
      this.AnimatorPropertyToNetcode(this.Parameters[index].type, this.Parameters[index].nameHash, index, this.StatePtr);
  }

  private unsafe void Properties_NetcodeToAnimator()
  {
    for (int index = 0; index < this.Parameters.Length; ++index)
      this.NetcodeToAnimatorProperty(this.Parameters[index].type, this.Parameters[index].nameHash, index, this.StatePtr);
  }

  private unsafe void Properties_NetcodeToAnimator_Lerp(int* from, int* to, float alpha)
  {
    for (int index = 0; index < this.Parameters.Length; ++index)
      this.NetcodeToAnimatorPropertyLerp(this.Parameters[index].type, this.Parameters[index].nameHash, index, from, to, alpha);
  }

  private unsafe void AnimatorPropertyToNetcode(
    AnimatorControllerParameterType type,
    int proHash,
    int index,
    int* data)
  {
    switch (type)
    {
      case AnimatorControllerParameterType.Float:
        int* data1 = &0;
        NetickUnityUtils.SetFloat(data1, this.Animator.GetFloat(proHash), 999.999939f);
        Entity.InternalDirtify((INetickNetworkScript) this, data1, this.StatePtr + index, 1, 0);
        break;
      case AnimatorControllerParameterType.Int:
        Entity.InternalDirtify((INetickNetworkScript) this, &this.Animator.GetInteger(proHash), this.StatePtr + index, 1, 0);
        break;
      case AnimatorControllerParameterType.Bool:
        Entity.InternalDirtify((INetickNetworkScript) this, &(this.Animator.GetBool(proHash) ? 1 : 0), this.StatePtr + index, 1, 0);
        break;
      case AnimatorControllerParameterType.Trigger:
        Entity.InternalDirtify((INetickNetworkScript) this, &(this.Animator.GetBool(proHash) ? 1 : 0), this.StatePtr + index, 1, 0);
        break;
    }
  }

  private unsafe void NetcodeToAnimatorPropertyLerp(
    AnimatorControllerParameterType type,
    int proHash,
    int index,
    int* fromP,
    int* toP,
    float alpha)
  {
    switch (type)
    {
      case AnimatorControllerParameterType.Float:
        this.Animator.SetFloat(proHash, this.InterpolateFloat(fromP + index, toP + index, alpha));
        break;
      case AnimatorControllerParameterType.Int:
        this.Animator.SetInteger(proHash, fromP[index]);
        break;
      case AnimatorControllerParameterType.Bool:
        this.Animator.SetBool(proHash, fromP[index] == 1);
        break;
      case AnimatorControllerParameterType.Trigger:
        int num1 = this.ProToLastValue[index];
        int num2 = fromP[index];
        int num3 = num2;
        if (num1 != num3 && num2 == 1 && (!this.IsPredicted || this._interpolationSource == InterpolationSource.RemoteSnapshot))
          this.Animator.SetTrigger(proHash);
        this.ProToLastValue[index] = num2;
        break;
    }
  }

  private unsafe void NetcodeToAnimatorProperty(
    AnimatorControllerParameterType type,
    int proHash,
    int index,
    int* data)
  {
    switch (type)
    {
      case AnimatorControllerParameterType.Float:
        this.Animator.SetFloat(proHash, NetickUnityUtils.GetFloat(data + index, 1f / 1000f));
        break;
      case AnimatorControllerParameterType.Int:
        this.Animator.SetInteger(proHash, data[index]);
        break;
      case AnimatorControllerParameterType.Bool:
        this.Animator.SetBool(proHash, data[index] == 1);
        break;
      case AnimatorControllerParameterType.Trigger:
        int num1 = this.ProToLastValue[index];
        int num2 = data[index];
        int num3 = num2;
        if (num1 != num3 && num2 == 1 && (!this.IsPredicted || this._interpolationSource == InterpolationSource.RemoteSnapshot))
          this.Animator.SetTrigger(proHash);
        this.ProToLastValue[index] = num2;
        break;
    }
  }

  private unsafe float InterpolateFloat(int* fromP, int* toP, float alpha)
  {
    return Mathf.Lerp(NetickUnityUtils.GetFloat(fromP, 1f / 1000f), NetickUnityUtils.GetFloat(toP, 1f / 1000f), alpha);
  }

  [Flags]
  [Serializable]
  public enum NetworkAnimatorRepConditions
  {
    SyncParameters = 1,
    SyncLayerWeights = 2,
    SyncState = 4,
  }
}
